package utils

import (
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"time"
)

func getVerbosity() int {
	v := os.Getenv("VERBOSE")
	level := 0
	if v != "" {
		var err error
		level, err = strconv.Atoi(v)
		if err != nil {
			log.Fatalf("Invalid verbosity %v", v)
		}
	}
	return level
}

type LogTopic string

const (
	dClient  LogTopic = "CLNT"
	dCommit  LogTopic = "CMIT"
	dDrop    LogTopic = "DROP"
	dError   LogTopic = "ERRO"
	dInfo    LogTopic = "INFO"
	dLeader  LogTopic = "LEAD"
	dLog     LogTopic = "LOG1"
	dLog2    LogTopic = "LOG2"
	dPersist LogTopic = "PERS"
	dSnap    LogTopic = "SNAP"
	dTerm    LogTopic = "TERM"
	dTest    LogTopic = "TEST"
	dTimer   LogTopic = "TIMR"
	dTrace   LogTopic = "TRCE"
	dVote    LogTopic = "VOTE"
	dWarn    LogTopic = "WARN"
)

var debugStart time.Time
var debugVerbosity int

var socket *net.UDPConn = nil

func init() {
	debugVerbosity = getVerbosity()
	debugStart = time.Now()

	log.SetFlags(log.Flags() &^ (log.Ldate | log.Ltime | log.Llongfile))

	if debugVerbosity >= 2 {
		for {
			var err error = nil
			socket, err = net.DialUDP("udp4", nil, &net.UDPAddr{
				IP:   net.IPv4(127, 0, 0, 1),
				Port: 2333,
			})
			if err != nil {
				fmt.Println("连接失败!", err)
				time.Sleep(10 * time.Millisecond)
				continue
			} else {
				break
			}
		}
	}
}
func Print(topic LogTopic, format string, a ...interface{}) {

	t := time.Since(debugStart).Microseconds()
	t /= 100
	prefix := fmt.Sprintf("%06d %v ", t, string(topic))
	format = prefix + format
	log.Printf(format, a...)

}

func Debug(topic LogTopic, format string, a ...interface{}) {
	if debugVerbosity >= 1 {
		t := time.Since(debugStart).Microseconds()
		t /= 100
		prefix := fmt.Sprintf("%06d %v ", t, string(topic))
		format = prefix + format
		log.Printf(format, a...)

		err := errors.New("tp")

		// 发送数据
		if debugVerbosity >= 2 {

			for err != nil {

				senddata := []byte(fmt.Sprintf(format, a...))
				_, err = socket.Write(senddata)
				if err != nil {
					time.Sleep(10 * time.Millisecond)
					continue
				}
				break
			}
		}
	}
}

func Assert(v bool) {
	if !v {
		panic("Assert Failed")
	}
}
